package typedefault

import (
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/utils"
	"os"
	"regexp"
	"strconv"
	"strings"
)

type TypeFileTool struct {
	Addr        string
	ThreadStore *structdef.ThreadStore
}

func (f *TypeFileTool) CreateTypeDefault(addr string, threadStore *structdef.ThreadStore, parameter ...string) {
	fUtil := &TypeFileTool{
		Addr:        addr,
		ThreadStore: threadStore,
	}
	store.AddTypeDefaultInstanceStore(threadStore, f.GetTypeName(), addr, fUtil)
}

func (a *TypeFileTool) GetData() interface{} {
	return nil
}
func (a *TypeFileTool) ToStr() string {
	return ""
}

func (f *TypeFileTool) SetAddr(addr string) {
	f.Addr = addr
}

func (f *TypeFileTool) SetThreadStore(threadStore *structdef.ThreadStore) {
	f.ThreadStore = threadStore
}

func (a *TypeFileTool) ParameterProcessing(parameter []string) []string {
	for i := range parameter {
		StrToHandle(&parameter[i])
	}
	return parameter
}

// 获取文件大小
func (f *TypeFileTool) GetFileSize(path string) string {
	file := f.OpenFile(path)
	defer file.Close()
	fileInfo, err := file.Stat()
	if err != nil {
		panic(err)
	}
	return strconv.FormatInt(fileInfo.Size(), 10)
}

// 获取文件最近修改时间
func (f *TypeFileTool) GetFileModTime(path string) string {
	file := f.OpenFile(path)
	defer file.Close()
	fileInfo, err := file.Stat()
	if err != nil {
		panic(err)
	}
	time := fileInfo.ModTime()
	// 2006-01-02 15:04:05
	return StringToStr(time.Format("2006-01-02 15:04:05"))

}

// 获取文件权限
func (f *TypeFileTool) GetFileMode(path string) string {
	file := f.OpenFile(path)
	defer file.Close()
	fileInfo, err := file.Stat()
	if err != nil {
		panic(err)
	}
	return StringToStr(fileInfo.Mode().String())
}

// 判断所给路径文件/文件夹是否存在
func (f *TypeFileTool) Exists(path string) string {
	fileLineRead, err := os.OpenFile(path, os.O_RDONLY, 0755)
	defer fileLineRead.Close()
	_, err = fileLineRead.Stat()
	if err != nil {
		if os.IsExist(err) {
			return strconv.FormatBool(true)
		}
		return strconv.FormatBool(false)
	}
	return strconv.FormatBool(true)
}

// 是否是文件
func (f *TypeFileTool) IsDir(path string) string {
	file, err := os.OpenFile(path, os.O_RDONLY, 0755)
	defer file.Close()
	fileInfo, err := file.Stat()
	if err != nil {
		return strconv.FormatBool(false)
	}
	return strconv.FormatBool(fileInfo.IsDir())
}

// 判断所给路径是否为文件
func (f *TypeFileTool) IsFile(path string) string {
	exists := f.Exists(path)
	parseBool, _ := strconv.ParseBool(exists)
	if !parseBool {
		return strconv.FormatBool(false)
	}
	dir := f.IsDir(path)
	parseBool, _ = strconv.ParseBool(dir)
	return strconv.FormatBool(!parseBool)
}

// 创建文件
func (f *TypeFileTool) CreateFile(path string) {
	f1, e := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755)
	if e != nil {
		panic(e)
	}
	err := f1.Close()
	if err != nil {
		panic(err)
	}
}

// 创建文件夹
func (f *TypeFileTool) CreateDir(path string) {
	e := os.MkdirAll(path, 0755)
	if e != nil {
		panic(e)
	}
}

// 获取临时目录
func (f *TypeFileTool) GetTempDir() string {
	return StringToStr(os.TempDir())
}

// 创建临时文件夹
func (f *TypeFileTool) CreateTempDir(dirName string) string {
	dir, err := os.MkdirTemp("", dirName)
	if err != nil {
		panic(err)
	}
	return StringToStr(dir)
}

// 创建临时文件
/*
	dir:临时文件夹,(全路径) ,可以使用CreateTempDir创建,如果为空,则使用系统默认临时文件夹GetTempDir
	filenName:文件名
*/
func (f *TypeFileTool) CreateTempFile(dir, filenName string) string {
	file, err := os.CreateTemp(dir, filenName)
	if err != nil {
		panic(err)
	}
	return StringToStr(file.Name())
}

// 获取当前项目根目录
func (f *TypeFileTool) GetCurrentPath() string {
	dir, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return StringToStr(dir)
}

// 系统路径分隔符
func (f *TypeFileTool) GetPathSeparator() string {
	return StringToStr(string(os.PathSeparator))
}

// 删除文件或目录,如果是目录,则删除目录下所有文件
func (f *TypeFileTool) RemoveFile(path string) {
	var fileList []string
	//判断是否存在,
	if strings.Contains(path, ",") {
		fileList = strings.Split(path, ",")
	} else {
		fileList = append(fileList, path)
	}
	for _, v := range fileList {
		err := os.RemoveAll(v)
		if err != nil {
			panic(err)
		}
	}
}

// 复制文件或目录,如果是目录,则复制目录下所有文件
func (f *TypeFileTool) CopyFile(oldPath string, newPath string) {
	var fileList []string
	//判断是否存在,
	if strings.Contains(oldPath, ",") {
		fileList = strings.Split(oldPath, ",")
	} else {
		fileList = append(fileList, oldPath)
	}
	utils.CopyFiles(fileList, newPath)
}

// 移动文件或目录,如果是目录,则移动目录下所有文件,也可以用来重命名
func (f *TypeFileTool) MoveFile(oldPath string, newPath string) {
	var fileList []string
	//判断是否存在,
	if strings.Contains(oldPath, ",") {
		fileList = strings.Split(oldPath, ",")
	} else {
		fileList = append(fileList, oldPath)
	}
	utils.MoveFiles(fileList, newPath)
}

// 获取指定文件夹下的所有文件(包含目录),mode=0读取当前文件夹(默认),Mode=1递归,返回List
func (f *TypeFileTool) GetFileList(path string, mode string) string {
	var fileList []string
	if mode == "1" {
		utils.GetFiles(path, &fileList, true)
	} else {
		utils.GetFile(path, &fileList, true)
	}

	return globalfunc.ExecuteFunc("SliceToList", fileList, f.ThreadStore).(string)
}

// 搜索文件,返回List
func (f *TypeFileTool) SearchFile(dir string, regexpStr string) string {
	var fileList []string
	utils.SearchFiles(dir, &fileList, regexp.MustCompile(regexpStr))
	return globalfunc.ExecuteFunc("SliceToList", fileList, f.ThreadStore).(string)
}

// zip压缩
// src = "F:\\1.xlsx"
// dst = "F:\\b.zip"
func (f *TypeFileTool) ZipFile(stc string, dir string) {
	err := utils.Zip(stc, dir)
	if err != nil {
		panic(err)
	}
}

// zip解压
func (f *TypeFileTool) UnZipFile(stc string, dir string) {
	err := utils.UnZip(stc, dir)
	if err != nil {
		panic(err)
	}
}

// Tar压缩
func (f *TypeFileTool) TarFile(stc string, dir string) {
	err := utils.Tar(stc, dir)
	if err != nil {
		panic(err)
	}
}

// Tar解压
func (f *TypeFileTool) UnTarFile(stc string, dir string) {
	err := utils.UnTar(stc, dir)
	if err != nil {
		panic(err)
	}
}

// Gz压缩
func (f *TypeFileTool) GzFile(stc string, dir string) {
	utils.DoGzipFile(stc, dir)
}

// Gz解压
func (f *TypeFileTool) UnGzFile(stc string, dir string) {
	utils.UnGzipPath(stc, dir)
}

func (f *TypeFileTool) GetDef() string {
	return `
		@CodeManual(def="FileTool.xxx",des="文件操作工具类")
		type share FileTool{
			def init{
				core&CreateTypeDefault()
			}
			@CodeManual(def="FileTool.size(path)",des="获取文件大小")
			def size{
				to core&GetFileSize($1)	
			}
			
			@CodeManual(def="FileTool.modTime(path)",des="获取文件修改时间")
			def modTime{
				to core&GetFileModTime($1)	
			}
			
			@CodeManual(def="FileTool.power(path)",des="获取文件权限")
			def power{
				to core&GetFileMode($1)	
			}
			
			@CodeManual(def="FileTool.exists(path)",des="获取文件或目录是否存在")
			def exists{
				to core&Exists($1)	
			}
			
			@CodeManual(def="FileTool.isFile(path)",des="是文件")
			def isFile{
				to core&IsFile($1)	
			}
		
			@CodeManual(def="FileTool.isDir(path)",des="是目录")
			def isDir{
				to core&IsDir($1)	
			}

  			
			@CodeManual(def="FileTool.createFile(path)",des="创建文件,如果文件存在,则跳过")
			def createFile{
				core&CreateFile($1)	
			}			
			
			@CodeManual(def="FileTool.createDir(dirPath)",des="创建目录,递归")
			def createDir{
				core&CreateDir($1)	
			}	

	      
			@CodeManual(def="FileTool.getTempDir()",des="获取当前系统的临时目录")
			def getTempDir{
				to core&GetTempDir()	
			}	

			
			@CodeManual(def="FileTool.createTempDir(path)",des="创建临时文件夹,返回路径")
			def createTempDir{
				to core&CreateTempDir($1)	
			}	

			//创建临时文件,临时目录dir可以省略,如果想在指定临时目录下创建临时文件
			//那么这个目录需要全路径,可以通过createTempDir创建返回的值
			@CodeManual(def="FileTool.createTempFile(dirPath,filePath)",des="创建临时文件,返回路径")
			def createTempFile{
				to core&CreateTempFile($1,$2)	
			}	

			
			@CodeManual(def="FileTool.currentPath()",des="当前执行目录的路径")
			def currentPath{
				to core&GetCurrentPath()	
			}	

			
			@CodeManual(def="FileTool.pathSeparator()",des="系统路径分隔符")
			def pathSeparator{
				to core&GetPathSeparator()	
			}	


			@CodeManual(def="FileTool.pathSeparator()",des="删除文件或目录(递归)")
			def del{
				to core&RemoveFile($1)	
			}	

			//复制文件或目录到目标位置,存在就会被覆盖
			//$1 可以用逗号分割同时处理多个路径
			//$2 目标目录
			@CodeManual(def="FileTool.copy(oldPath,newDir)",des="复制文件或目录到目标位置,存在就会被覆盖，还可用来重命名文件")
			def copy{
				to core&CopyFile($1,$2)	
			}


			//移动文件或目录(递归)    
			//$1和$2类型必须一致 ,比如都是文件，或者都是目录
			//oldPath可以用逗号分割同时处理多个路径
			@CodeManual(def="FileTool.move(oldPath,newPath)",des="移动文件或目录(递归)  ")
			def move{
				to core&MoveFile($1,$2)	
			}
			@CodeManual(def="FileTool.getFiles(path,mode)",des="获取指定文件夹下的所有文件,mode=0读取当前文件夹(默认),Mode=1递归,返回List")
			def getFiles{
				to core&GetFileList($1,$2)	
			}


			@CodeManual(def="FileTool.search(dirPath,regex)",des="基于dir搜索文件file(支持正则表达式) ,返回List")
			def search{
				to core&SearchFile($1,$2)	
			}
			
			@CodeManual(def="FileTool.zip(src,dst)",des="将stc压缩到dst目录下")
			def zip{
				core&ZipFile($1,$2)	
			}

			
			@CodeManual(def="FileTool.unZip(src,dst)",des="将stc解压到dst目录下")
			def unZip{
				core&UnZipFile($1,$2)	
			}

			
			@CodeManual(def="FileTool.tar(src,dst)",des="将stc压缩到dst目录下")
			def tar{
				core&TarFile($1,$2)	
			}

	
			@CodeManual(def="FileTool.unTar(src,dst)",des="将stc解压到dst目录下")
			def unTar{
				core&UnTarFile($1,$2)	
			}

			
			@CodeManual(def="FileTool.gz(src,dst)",des="将stc压缩到dst目录下")
			def gz{
				core&GzFile($1,$2)	
			}
			
			@CodeManual(def="FileTool.ungz(src,dst)",des="将stc解压到dst目录下")
			def ungz{
				core&UnGzFile($1,$2)	
			}

		}
	`
}

func (f *TypeFileTool) GetTypeName() string {
	return "FileTool"
}

func init() {
	RegisterTypeDefault(&TypeFileTool{})
}

// 如果当前path和上次path不一致,则关闭上次path,并打开当前path
func (f *TypeFileTool) OpenFile(path string) *os.File {
	fileLineRead, err := os.OpenFile(path, os.O_RDONLY, 0755)
	if err != nil {
		panic(err)
	}
	return fileLineRead
}
